<template>
  <div
    :class="['dpro-progress', layout, `with-text-${textPosition}`]"
    :style="{
      '--d': `${animationDelay}ms`,
      '--labelWidth': pxToRem(labelWidth),
      '--textWidth': pxToRem(textWidth),
      'height': comHeight
    }"
    ref="dproProgress"
  >
    <div class="progress-label-wrapper">
      <animate-text
        :text="label"
        :animateStyle="labelAnimateStyle"
        :animationDelay="animationDelay"
        :textStyle="formatLabelStyle"
      />
      <div class="text-top" v-if="textPosition === 'top'">
        <animate-number-business
          :value="format(percent)"
          :percent="percent"
          :animationDelay="percentAniDelay"
          :textStyle="formatTextStyle"
        />
      </div>
    </div>
    <div class="progress-outer-wrapper">
      <div class="progress-outer">
        <div
          class="progress-inner"
          :style="{
            'border-radius': strokeLinecap === 'square' ? '0' : '100px'
          }"
        >
          <div
            class="progress-bg"
            :style="{
              width: percent + '%',
              height: pxToRem(strokeWidth + 'px'),
              background: strokeColor,
              'border-radius': strokeLinecap === 'square' ? '0' : '100px'
            }"
          ></div>
          <!-- <div class="text-inner" v-if="textPosition === 'inner'">{{ format(percent) }}</div> -->
          <div class="text-inner" v-if="['inner', 'follow'].includes(textPosition)">
            <animate-number-business
              :value="format(percent)"
              :percent="percent"
              :animationDelay="percentAniDelay"
              :textStyle="formatTextStyle"
            />
          </div>
        </div>
      </div>
      <div class="progress-extra" v-if="textPosition === 'right'">
        <animate-number-business
          :value="format(percent)"
          :percent="percent"
          :animationDelay="percentAniDelay"
          :textStyle="formatTextStyle"
        />
      </div>
    </div>
  </div>
</template>

<script>
import { pxToRem, isObject } from "../../../utils/util";
import AnimateNumberBusiness from "./animate-number-business.vue";
import AnimateText from "./animate-text.vue";
export default {
  name: 'DproProgress',
  props: {
    // 高度
    height: {
      type: [Number, String],
      default: 'auto'
    },
    // 标题
    label: {
      type: String,
      default: ''
    },
    // 标题样式
    labelStyle: {
      type: Object,
      default: () => {}
    },
    // 标题占宽 - 水平布局下有效
    labelWidth: {
      type: [Number, String],
      default: '20%'
    },
    // label动画形式：opacity、scale
    labelAnimateStyle: {
      type: String,
      default: 'opacity'
    },
    // 进度百分比，0-100
    percent: {
      type: Number,
      default: 0
    },
    // 内容的模版函数
    format: {
      type: Function,
      default: (percent) => percent + '%'
    },
    // 布局类型，'horizontal'水平布局，'vertical'垂直布局
    layout: {
      type: String,
      default: 'horizontal'
    },
    // 文字(数量、百分比等)位置，'right'外部右侧，'inner'内部，'top'顶部右侧(仅在layout垂直布局时有效)，'follow'进度条右侧跟随，'none'隐藏不显示
    textPosition: {
      type: String,
      default: 'right'
    },
    // 文字数据样式
    textStyle: {
      type: Object,
      default: () => {}
    },
    // 数据文字占宽 - textPositon在right/follow下有效
    textWidth: {
      type: [Number, String],
      default: '15%'
    },
    // 进度条圆角，'square':直角，'round':圆角
    strokeLinecap: {
      type: String,
      default: 'round'
    },
    // 进度条线宽，单位px
    strokeWidth: {
      type: Number,
      default: 10
    },
    // 进度条背景色
    strokeColor: {
      type: String,
      default: '#357DFF'
    },
    // 动画延迟时间（ms）
    animationDelay: {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      
    }
  },
  computed: {
    comHeight() {
      return typeof(this.height) === 'number' ? pxToRem(`${this.height}px`) : this.height;
    },
    // 数字动画延迟，在整体延迟的基础上增加100ms，等进度条动画开始后再展示数字动画
    percentAniDelay() {
      return this.animationDelay + 100;
    },
    // 转化单位后的labelStyle
    formatLabelStyle() {
      return this.formatStyleObj(this.labelStyle);
    },
    // 转化单位后的textStyle
    formatTextStyle() {
      return this.formatStyleObj(this.textStyle);
    }
  },
  components: {
    AnimateNumberBusiness,
    AnimateText
  },
  mounted() {
  },
  methods: {
    pxToRem,
    formatStyleObj(styleObj) {
      if(!isObject(styleObj)) return styleObj;
      let result = {};
      for(let key in styleObj) {
        result[key] = pxToRem(styleObj[key]);
      }
      return result;
    }
  }
}
</script>

<style lang="less" scoped>
@duration: 0.4s;
.dpro-progress {
  font-size: 14px;
  display: flex;
  &.vertical {
    flex-direction: column;
    .progress-label-wrapper {
      text-align: left;
      font-size: 14px;
      line-height: 18px;
      margin-bottom: 7px;
      overflow: hidden;
      display: flex;
      align-items: center;
      justify-content: space-between;
      /deep/ .progress-label {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
      .text-top {
        padding: 0 16px;
      }
    }
    .progress-outer-wrapper {
      flex: auto;
      min-width: 0;
      display: flex;
      align-items: center;
    }
  }
  &.horizontal {
    align-items: center;
    .progress-label-wrapper {
      flex: 0 0 var(--labelWidth, 20%);
      width: var(--labelWidth, 20%);
      text-align: right;
      margin-right: 14px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .progress-outer-wrapper {
      flex: auto;
      min-width: 0;
      display: flex;
      align-items: center;
    }
  }
  &.with-text-follow {
    .progress-inner {
      background-color: transparent;
      display: flex;
      align-items: center;
      padding-right: var(--textWidth, 15%);
      .progress-bg {
        flex-shrink: 0;
      }
    }
    .text-inner {
      position: static;
      margin-left: 11px;
    }
  }
}
.progress-outer {
  flex: auto;
  min-width: 0;
  // width: 65%;
  animation: fadeInLeft @duration cubic-bezier(0.16, 0.72, 0.23, 1.01) both;
  animation-delay: var(--d, 0);
}
.progress-inner {
  position: relative;
  width: 100%;
  overflow: hidden;
  background-color: rgba(255, 255, 255, 0.1);
}
.progress-bg {
  width: 0;
  // transition: all .8s cubic-bezier(0.08, 0.82, 0.69, 0.99);
  animation: fadeInLeft .8s cubic-bezier(0.16, 0.72, 0.23, 1.01) both;
  animation-delay: var(--d, 0);
}
.text-inner {
  position: absolute;
  left: 58%;
  top: 0;
  height: 100%;
  font-size: 14px;
  display: flex;
  align-items: center;
  animation: fadeIn @duration both @duration;
}
.progress-extra {
  flex: 0 0 var(--textWidth, 15%);
  width: var(--textWidth, 15%);
  margin-left: 14px;
}
.fade-left {
  animation: fadeInLeft @duration both;
  animation-delay: var(--d, 0);
}
@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes fadeInLeft {
  0% {
    opacity: 0;
    clip-path: inset(0 100% 0 0);
  }
  // 10% {
  //   opacity: 0.4;
  // }
  100% {
    opacity: 1;
    clip-path: inset(0 0 0 0);
  }
}
</style>